package cn.elwy.rcp.ui.util;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;

/**
 * 根据传入的参数，设置表格的列名、列宽和行高等
 * 
 * @author huangsq
 * @version 1.0, 2013-11-20
 * @since 1.0, 2013-11-20
 */
public class WidgetUtil {

  /**
   * 设置表格列名、宽度和高度
   * 
   * @param table
   * @param columnsName
   * @param columnsWidth
   */
  public static void setTableColumn(Table table, String[] columnsName, int[] columnsWidth) {
    table.addListener(SWT.MeasureItem, new Listener() {
      public void handleEvent(Event event) {
        event.height = 16;
      }
    });
    for (int i = 0; i < columnsName.length; i++) {
      new TableColumn(table, SWT.NONE).setText(columnsName[i]);
      table.getColumn(i).setWidth(columnsWidth[i]);
    }
  }

  /**
   * 设置表格列名、宽度和高度
   * 
   * @param table
   * @param columnsName
   * @param columnsWidth
   * @param rowHeight
   */
  public static void setTableColumn(Table table, String[] columnsName, int[] columnsWidth, final int rowHeight) {
    table.addListener(SWT.MeasureItem, new Listener() {
      public void handleEvent(Event event) {
        event.height = rowHeight;
      }
    });
    for (int i = 0; i < columnsName.length; i++) {
      new TableColumn(table, SWT.NONE).setText(columnsName[i]);
      table.getColumn(i).setWidth(columnsWidth[i]);
    }
  }

  /**
   * 设置表格行高度
   * 
   * @param table
   * @param rowHeight
   */
  public static void setRowHeight(Table table, final int rowHeight) {
    table.addListener(SWT.MeasureItem, new Listener() {
      public void handleEvent(Event event) {
        event.height = rowHeight;
      }
    });
  }

  /**
   * 设置树行高度
   * 
   * @param tree
   * @param rowHeight
   */
  public static void setRowHeight(Tree tree, final int rowHeight) {
    tree.addListener(SWT.MeasureItem, new Listener() {
      public void handleEvent(Event event) {
        event.height = rowHeight;
      }
    });
  }

  /**
   * 设置列表行高度
   * 
   * @param list
   * @param rowHeight
   */
  public static void setRowHeight(org.eclipse.swt.widgets.List list, final int rowHeight) {
    list.addListener(SWT.MeasureItem, new Listener() {
      public void handleEvent(Event event) {
        event.height = rowHeight;
      }
    });
  }

  /**
   * 为表列添加排序功能
   * 
   * @param table 表格
   * @param column 表列
   */
  public static void addSorter(final Table table, final TableColumn column) {
    column.addListener(SWT.Selection, new Listener() {
      boolean isAscend = true;
      Collator comparator = Collator.getInstance(Locale.getDefault());

      public void handleEvent(Event e) {
        int columnIndex = getColumnIndex(table, column);
        TableItem[] items = table.getItems();

        for (int i = 1; i < items.length; i++) {
          String value2 = items[i].getText(columnIndex);
          for (int j = 0; j < i; j++) {
            String value1 = items[j].getText(columnIndex);
            boolean isLessThan = comparator.compare(value2, value1) < 0;
            if ((isAscend && isLessThan) || (!isAscend && !isLessThan)) {
              String[] values = getTableItemText(table, items[i]);
              Image image = items[i].getImage();
              Object obj = items[i].getData();
              boolean chck = items[i].getChecked();
              items[i].dispose();

              TableItem item = new TableItem(table, SWT.NONE, j);
              item.setChecked(chck);
              item.setImage(image);
              item.setText(values);
              item.setData(obj);
              items = table.getItems();
              break;
            }
          }
        }

        table.setSortColumn(column);
        table.setSortDirection((isAscend ? SWT.UP : SWT.DOWN));
        isAscend = !isAscend;
      }
    });
  }

  private static int getColumnIndex(Table table, TableColumn column) {
    TableColumn[] columns = table.getColumns();
    for (int i = 0; i < columns.length; i++) {
      if (columns[i].equals(column))
        return i;
    }
    return -1;
  }

  /**
   * 根据鼠标单击的位置获取列的索引
   * 
   * @param table 表格
   * @param mouseEvent 鼠标事件
   * @return
   */
  public static int getColumnIndex(final Table table, final MouseEvent mouseEvent) {
    if (table.getSelection() == null || table.getSelection().length == 0) {
      return -1;
    }
    TableItem tableItem = (TableItem) table.getSelection()[0];
    Point point = new Point(mouseEvent.x, mouseEvent.y);
    for (int i = 0; i < table.getColumnCount(); i++) {
      if (tableItem.getBounds(i).contains(point)) {
        return i;
      }
    }
    return -1;
  }

  private static String[] getTableItemText(Table table, TableItem item) {
    int count = table.getColumnCount();
    String[] strs = new String[count];
    for (int i = 0; i < count; i++) {
      strs[i] = item.getText(i);
    }
    return strs;
  }

  /**
   * 列自适应表格宽度
   * 
   * @param table 表格
   * @param index 自适应宽度的列索引号，索引下标从0开始
   */
  public static void autoTableWidth(final Table table, final int index) {
    autoTableWidth(0, table, index);
  }

  /**
   * 列自适应表格宽度
   * 
   * @param minWidth 自动调整列最小宽度
   * @param table 表格
   * @param index 自适应宽度的列索引号，索引下标从0开始
   */
  public static void autoTableWidth(final int minWidth, final Table table, final int index) {
    table.addControlListener(new ControlAdapter() {
      public void controlResized(final ControlEvent event) {
        int columnCount = table.getColumnCount();
        if (columnCount <= index) {
          return;
        }
        // 固定的列总宽度
        int fixWidth = table.getBorderWidth() * 2;
        for (int i = 0; i < columnCount; i++) {
          if (i != index) {
            fixWidth += table.getColumn(i).getWidth();
          }
        }
        TableColumn tableColumn = table.getColumn(index);
        int width = table.getBounds().width - fixWidth;
        if (width < minWidth && minWidth != 0) {
          width = minWidth;
        }
        tableColumn.setWidth(width);
      }
    });
  }

  /**
   * 列自适应表格宽度
   * 
   * @param table 表格
   */
  public static void autoColumnWidth(final Table table) {
    autoColumnWidth(0, table);
  }

  /**
   * 列自适应表格宽度
   * 
   * @param table 表格
   * @param fixIndex 固定宽度的列索引号，索引下标从0开始
   */
  public static void autoColumnWidth(final Table table, final int... fixIndex) {
    autoColumnWidth(0, table, fixIndex);
  }

  /**
   * 列自适应表格宽度
   * 
   * @param minWidth 自动调整列最小宽度
   * @param table 表格
   * @param fixIndex 固定宽度的列索引号，索引下标从0开始
   */
  public static void autoColumnWidth(final int minWidth, final Table table, final int... fixIndex) {
    table.addControlListener(new ControlAdapter() {

      public void controlResized(final ControlEvent e) {
        int columnCount = table.getColumnCount();
        if (columnCount < 1) {
          return;
        }
        int average = columnCount - fixIndex.length <= 1 ? 1 : columnCount - fixIndex.length;
        // 原始的列总宽度
        int fixWidth = table.getBorderWidth() * 2;
        for (int i = 0; i < columnCount; i++) {
          fixWidth += table.getColumn(i).getWidth();
        }
        // 列宽计算公式:新列的宽度 = (新表格宽度 - 原始列宽度) / 需要调整的列数 + 旧列的宽度

        int adjustWidth = (table.getSize().x - fixWidth) / average;
        // System.out.println(adjustWidth + " = " + table.getSize().x + "-" + fixWidth + "/"
        // + (columnCount - fixIndex.length));
        Arrays.sort(fixIndex); // 如果数组无序，可能导致查不到
        for (int i = 0; i < columnCount; i++) {
          if (Arrays.binarySearch(fixIndex, i) < 0) { // 查找到的结果小于0表示未找到
            int width = adjustWidth + table.getColumn(i).getWidth();
            if (width < minWidth && minWidth != 0) {
              width = minWidth;
            }
            table.getColumn(i).setWidth(width);
          }
        }
      }
    });
  }

  /**
   * 添加光棒以及各行颜色差效果
   * 
   * @param table table
   */
  public static void rowLight(final Table table) {
    table.addMouseMoveListener(new MouseMoveListener() {
      public void mouseMove(MouseEvent e) {
        TableItem item = table.getItem(new Point(e.x, e.y));
        if (item != null) {
          Display display = Display.getCurrent();
          Color white = display.getSystemColor(SWT.COLOR_WHITE);
          Color lightShadow = display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
          Color yellow = display.getSystemColor(SWT.COLOR_YELLOW);
          for (int i = 0; i < table.getItemCount(); i++) {
            if (i % 2 == 0) {
              table.getItem(i).setBackground(white);
            } else {
              table.getItem(i).setBackground(lightShadow);
            }
          }
          table.indexOf(item);
          item.setBackground(yellow);
        }
      }
    });
  }

  private static Map<Table, List<CLabel>> numberLabelForTable;

  public static void setItemsNumber(TableViewer tableViewer) {
    if (numberLabelForTable == null) {
      numberLabelForTable = new HashMap<Table, List<CLabel>>();
    }
    Table table = tableViewer.getTable();
    List<CLabel> numberLabel = new ArrayList<CLabel>();
    List<CLabel> oldNumberLabel = (List<CLabel>) numberLabelForTable.get(table);
    if (oldNumberLabel != null) {
      for (Iterator<CLabel> iter = oldNumberLabel.iterator(); iter.hasNext();) {
        iter.next().dispose();
      }
    }
    Image image = new Image(Display.getDefault(), 1, 15);
    TableItem[] tableItem = table.getItems();
    TableEditor te[] = new TableEditor[tableItem.length];
    for (int i = 0; i < tableItem.length; i++) {
      te[i] = new TableEditor(table);
      te[i].horizontalAlignment = SWT.CENTER;
      te[i].grabHorizontal = true;
      final CLabel lbl = new CLabel(table, SWT.SHADOW_OUT);
      lbl.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
      lbl.setAlignment(SWT.CENTER);
      lbl.setEnabled(false);
      lbl.setText("" + (i + 1));
      te[i].setEditor(lbl, tableItem[i], 0);
      tableItem[i].setText((i + 1) + "");
      tableItem[i].setImage(image);
      numberLabel.add(lbl);
    }
    numberLabelForTable.put(table, numberLabel);
  }

  /**
   * 表格自动换行
   * 
   * @param table
   */
  public static void autoWordWrap(Table table) {
    Listener listener = new Listener() {
      public void handleEvent(Event event) {
        switch (event.type) {
        case SWT.MeasureItem: {
          TableItem item = (TableItem) event.item;
          String text = getText(item, event.index);
          Point size = event.gc.textExtent(text);
          event.width = size.x;
          event.height = Math.max(event.height, size.y);
          break;
        }
        case SWT.PaintItem: {
          TableItem item = (TableItem) event.item;
          String text = getText(item, event.index);
          Point size = event.gc.textExtent(text);
          int offset2 = event.index == 0 ? Math.max(0, (event.height - size.y) / 2) : 0;
          event.gc.drawText(text, event.x, event.y + offset2, true);
          break;
        }
        case SWT.EraseItem: {
          event.detail &= ~SWT.FOREGROUND;
          break;
        }
        }
      }

      String getText(TableItem item, int column) {
        return item.getText(column);
      }
    };
    table.addListener(SWT.MeasureItem, listener);
    table.addListener(SWT.PaintItem, listener);
    table.addListener(SWT.EraseItem, listener);
  }

}